﻿using System;
using System.Collections.Generic;
using UnityEngine;
using Yoozoo.Framework.Core;
using Yoozoo.Libs;
using Yoozoo.Managers.ResourceManagerV2.Runtime;

namespace Gameplay.PVE.Survivor
{
    /// <summary>
    /// 战斗中的资产代理器
    /// </summary>
    public class BattleGameObject : IClass
    {
        public int resId;
        private GameObject gameObject;
        private Transform transform;
        private bool gameObjectReady;
        private Action<GameObject> callback;
        private string path;
        private bool isUsing;
        private bool isLoading;
        
        public bool IsReady => gameObjectReady;

        public void Create(string path, Action<GameObject> callback)
        {
            this.ResetData();
            isUsing = true;
            this.callback = callback;
            this.path = path;
            gameObjectReady = false;
            isLoading = true;
            BattleResourceManager.Instance.LoadPrefabByPath(path, OnGameObjectReady);
        }

        protected virtual void OnGameObjectCreatedInternal(GameObject gameObject)
        {

        }
        
        protected virtual void OnGameObjectReadyInternal(GameObject gameObject)
        {

        }

        protected virtual void OnGameObjectReleaseInternal()
        {

        }

        protected virtual void OnGameObjectDestroyInternal()
        {

        }

        private void OnGameObjectReady(bool success, string assetName, object asset)
        {
            isLoading = false;
            if (!isUsing)
            {
                //已经被销毁
                return;
            }
            gameObjectReady = true;
            if (asset == null)
            {
                UnityEngine.Debug.LogError("Load prefab failed: " + path);
                return;
            }

            gameObject = GameObject.Instantiate(asset as GameObject);
            transform = gameObject.transform;
            OnGameObjectCreatedInternal(gameObject);
            OnUsed();
        }

        public void OnUsed()
        {
            isUsing = true;
            SetTransformData();
            OnGameObjectReadyInternal(gameObject);
            if (callback != null)
            {
                callback.Invoke(gameObject);
                callback = null;
            }
        }

        private void SetTransformData()
        {
            if (position != defaultVector3)
            {
                transform.position = position;
            }
            if (forward != defaultVector3)
            {
                transform.forward = forward;
            }

            if (parent != null)
            {
                transform.SetParent(parent);
            }

            if (localPosition != defaultVector3)
            {
                transform.localPosition = localPosition;
            }

            if (eulerAngle != defaultVector3)
            {
                transform.eulerAngles = eulerAngle;
            }
            else if (localEulerAngle != defaultVector3)
            {
                transform.localEulerAngles = localEulerAngle;
            }

            
            if (scale != defaultVector3)
            {
                transform.localScale = scale;
            }

            gameObject.SetActive(active);
        }

        private Vector3 position;
        private Vector3 localPosition;
        private Vector3 eulerAngle;
        private Vector3 localEulerAngle;
        private Vector3 scale;
        private Vector3 forward;
        private Transform parent;
        private bool active;

        private static readonly Vector3 defaultVector3 = new Vector3(-999, -999, -999);

        private void ResetData()
        {
            isUsing = false;
            position = defaultVector3;
            localPosition = defaultVector3;
            forward = defaultVector3;
            eulerAngle = defaultVector3;
            scale = defaultVector3;
            localEulerAngle = defaultVector3;
            active = true;
            parent = null;
            callback = null;
        }

        public Vector3 LocalPosition
        {
            set
            {
                localPosition = value;
                if (gameObjectReady)
                {
                    transform.localPosition = localPosition;
                }
            }
            get
            {
                if (gameObjectReady)
                {
                    return transform.localPosition;
                }

                return localPosition;
            }
        }

        public Vector3 Position
        {
            set
            {
                position = value;
                if (gameObjectReady)
                {
                    transform.position = position;
                }
            }
            get
            {
                if (gameObjectReady)
                {
                    return transform.position;
                }

                return position;
            }
        }

        public Vector3 Forward
        {
            set
            {
                forward = value;
                if (gameObjectReady)
                {
                    transform.forward = forward;
                }
            }
            get
            {
                if (gameObjectReady)
                {
                    return transform.forward;
                }

                return forward;
            }
        }

        public Vector3 EulerAngle
        {
            set
            {
                eulerAngle = value;
                if (gameObjectReady)
                {
                    transform.eulerAngles = eulerAngle;
                }
            }
            get
            {
                if (gameObjectReady)
                {
                    return transform.eulerAngles;
                }

                return eulerAngle;
            }
        }

        public Vector3 LocalEulerAngle
        {
            set
            {
                localEulerAngle = value;
                if (gameObjectReady)
                {
                    transform.localEulerAngles = localEulerAngle;
                }
            }
            get
            {
                if (gameObjectReady)
                {
                    return transform.localEulerAngles;
                }

                return localEulerAngle;
            }
        }

        public Vector3 Scale
        {
            set
            {
                scale = value;
                if (gameObjectReady)
                {
                    transform.localScale = scale;
                }
            }
            get
            {
                if (gameObjectReady)
                {
                    return transform.localScale;
                }

                return scale;
            }
        }

        public bool Active
        {
            set
            {
                active = value;
                if (gameObjectReady)
                {
                    gameObject.SetActive(active);
                }
            }
            get
            {
                if (gameObjectReady)
                {
                    return gameObject.activeSelf;
                }

                return active;
            }
        }

        public Transform Parent
        {
            set
            {
                parent = value;
                if (gameObjectReady)
                {
                    transform.SetParent(parent);
                }
            }
            get
            {
                if (gameObjectReady)
                {
                    return transform.parent;
                }

                return parent;
            }
        }

        public void SetPrefabReadyAction(Action<GameObject> callback)
        {
            if (IsReady)
            {
                callback.Invoke(gameObject);
            }
            else
            {
                this.callback = callback;
            }
        }

        public GameObject GetChild(int index)
        {
            if (IsReady)
            {
                var temp = this.gameObject.transform.GetChild(index);
                if (temp)
                {
                    return temp.gameObject;
                }
            }
            return null;
        }

        public void OnReset()
        {
            this.callback = null;
        }

        public void OnRelease()
        {
            OnGameObjectReleaseInternal();
            ResetData();
        }

        public void Dispose()
        {
            if (gameObjectReady && gameObject != null)
            {
                GameObject.DestroyImmediate(gameObject);
            }
            ResetData();
            gameObject = null;
            gameObjectReady = false;
        }

        //如果正在加载中，则对象池中该对象暂时设定为不可用，等加载完成后销毁再使用
        public bool IsLoading => isLoading;
    }
}
